using System.Net.Http.Headers;
using MultiAgentsShared;

namespace MultiAgentsClient.Tools;

public struct HttpResult
{
    public string Content { get; set; }
    public byte[] Byte { get; set; }
    public string Error { get; set; }
    public int StatusCode { get; set; }

    public override readonly string ToString()
    {
        return $"Content: {Content}\n" +
               $"Error: {Error}\n" +
               $"StatusCode: {StatusCode}\n";
    }
}

[GptToolSet("HTTP Network ToolSet", "")]
public class HttpToolProvider
{
    private static readonly HttpClient httpClient = new();

    [GptFunc("Send HTTP request and get response without authentication", true)]
    public static async Task<HttpResult> SendHttpRequestAsync(
        [GptFuncParam("HTTP method like GET, POST, etc.")] string method,
        [GptFuncParam("URL to request")] string url,
        [GptFuncParam("Content body for POST requests (empty string if not needed)")] string content)
    {
        try
        {
            using var request = new HttpRequestMessage(new HttpMethod(method), url);

            if (!string.IsNullOrWhiteSpace(content) && (method.ToUpper() == "POST" || method.ToUpper() == "PUT"))
            {
                request.Content = new StringContent(content, System.Text.Encoding.UTF8, "application/json");
            }
            
            using HttpResponseMessage response = await httpClient.SendAsync(request);
            string responseContent = await response.Content.ReadAsStringAsync();

            return new HttpResult
            {
                Content = responseContent,
                StatusCode = (int)response.StatusCode,
                Error = string.Empty
            };
        }
        catch (Exception ex)
        {
            return new HttpResult
            {
                Content = string.Empty,
                Error = ex.Message,
                StatusCode = (int)System.Net.HttpStatusCode.InternalServerError
            };
        }
    }

    [GptFunc("Send HTTP request with Bearer authentication and get response.", true)]
    public static async Task<HttpResult> SendBearerAuthHttpRequestAsync(
        [GptFuncParam("HTTP method like GET, POST, etc.")] string method,
        [GptFuncParam("URL to request")] string url,
        [GptFuncParam("Authorization token")] string token,
        [GptFuncParam("Content body for POST requests (empty string if not needed)")] string content)
    {
        try
        {
            using var request = new HttpRequestMessage(new HttpMethod(method), url);
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);

            if (!string.IsNullOrWhiteSpace(content) && (method.ToUpper() == "POST" || method.ToUpper() == "PUT"))
            {
                request.Content = new StringContent(content, System.Text.Encoding.UTF8, "application/json");
            }

            using HttpResponseMessage response = await httpClient.SendAsync(request);
            string responseContent = await response.Content.ReadAsStringAsync();

            return new HttpResult
            {
                Content = responseContent,
                StatusCode = (int)response.StatusCode,
                Error = string.Empty
            };
        }
        catch (Exception ex)
        {
            return new HttpResult
            {
                Content = string.Empty,
                Error = ex.Message,
                StatusCode = (int)System.Net.HttpStatusCode.InternalServerError
            };
        }
    }

    [GptFunc("Send HTTP request with Basic authentication and get response.", true)]
    public static async Task<HttpResult> SendBasicAuthHttpRequestAsync(
        [GptFuncParam("HTTP method like GET, POST, etc.")] string method,
        [GptFuncParam("URL to request")] string url,
        [GptFuncParam("Username for Basic authentication")] string username,
        [GptFuncParam("Password for Basic authentication")] string password,
        [GptFuncParam("Read method like String or Byte")] string readAs,
        [GptFuncParam("Content body for POST requests (empty string if not needed)")] string content)
    {
        try
        {
            using var request = new HttpRequestMessage(new HttpMethod(method), url);
            var byteArray = System.Text.Encoding.ASCII.GetBytes($"{username}:{password}");
            var base64String = Convert.ToBase64String(byteArray);
            request.Headers.Authorization = new AuthenticationHeaderValue("Basic", base64String);

            if (!string.IsNullOrWhiteSpace(content) && (method.ToUpper() == "POST" || method.ToUpper() == "PUT"))
            {
                request.Content = new StringContent(content, System.Text.Encoding.UTF8, "application/json");
            }

            using HttpResponseMessage response = await httpClient.SendAsync(request);

            if (readAs.ToUpper() == "BYTE")
            {
                byte[] responseContent = await response.Content.ReadAsByteArrayAsync();

                return new HttpResult
                {
                    Byte = responseContent,
                    StatusCode = (int)response.StatusCode,
                    Error = string.Empty
                };
            }
            else
            {
                string responseContent = await response.Content.ReadAsStringAsync();

                return new HttpResult
                {
                    Content = responseContent,
                    StatusCode = (int)response.StatusCode,
                    Error = string.Empty
                };
            }
        }
        catch (Exception ex)
        {
            return new HttpResult
            {
                Content = string.Empty,
                Error = ex.Message,
                StatusCode = (int)System.Net.HttpStatusCode.InternalServerError
            };
        }
    }
}
